home *** CD-ROM | disk | FTP | other *** search
/ Mac Power 1997 January / macpower199701.bin / AMUG / Programming_10 / WASTE 1.3a1.sit / WASTE 1.3a1 Distribution / WASTE 1.3a1 / WEFontTables.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-08-23  |  8.5 KB  |  316 lines  |  [TEXT/CWIE]

  1. /*
  2.  *    WEFontTables.c
  3.  *
  4.  *    WASTE PROJECT
  5.  *  Font Mapping Tables
  6.  *
  7.  *  Copyright (c) 1993-1996 Marco Piovanelli
  8.  *    All Rights Reserved
  9.  *
  10.  *  C port by Dan Crevier
  11.  *
  12.  */
  13.  
  14.  
  15. #include "WASTEIntf.h"
  16.  
  17. enum {
  18.     weFontTableSignature            =    'FISH',
  19.     weCurrentFontTableVersion        =    0x01008000        //    1.0
  20. };
  21.  
  22. typedef struct {
  23.     FourCharCode ftSignature;    //    must be weFontTableSignature
  24.     UInt32 ftVersion;            //    font table version, in NumVersion format
  25.     UInt32 ftNumEntries;        //    entry count
  26.     UInt32 ftReserved;            //    reserved for future use
  27. } WEFontTableHeader, *WEFontTableHeaderPtr;
  28.  
  29. typedef struct {
  30.     SInt16 ftOldFontID;        //    font ID on save
  31.     SInt16 ftNewFontID;        //    font ID on re-open
  32.     SInt32 ftEncoding;        //    character encoding (currently = script code)
  33.     SInt32 ftReserved;        //    reserved for future use
  34.     UInt32 ftNameOffset;    //    offset to font name
  35. } WEFontTableEntry, *WEFontTableEntryPtr;
  36.  
  37. typedef struct {
  38.     WEFontTableHeader ftHeader;
  39.     WEFontTableEntry ftEntries [ kVariableLengthArray ];
  40.     //    packed font names follow
  41. } WEFontTable, *WEFontTablePtr, **WEFontTableHandle;
  42.  
  43. pascal OSErr WEBuildFontTable(Handle hFontTable, WEFontIDToNameUPP fontIDToNameProc, WEHandle hWE)
  44. {
  45.     Handle hStyles = nil;
  46.     StyleTableElementPtr pStyle, pStyle2;
  47.     WEFontTablePtr pFontTable;
  48.     SInt32 nStyles, styleIndex, styleIndex2;
  49.     WEFontTableEntry entry;
  50.     WEFontTableEntryPtr pEntry;
  51.     Str255 fontName;
  52.     SInt32 fontCount;
  53.     SInt32 fontNameOffset;
  54.     Size fontNameSize, offsetAdjustment;
  55.     Boolean saveStylesLock;
  56.     OSErr err;
  57.  
  58.     //    return an error code is hFontTable is nil
  59.     err = nilHandleErr;
  60.     if (hFontTable == nil)
  61.         goto cleanup;
  62.  
  63.     //    clone the style table, as we need a modifiable copy
  64.     hStyles = (Handle) (*hWE)->hStyles;
  65.     if ((err = HandToHand(&hStyles)) != noErr)
  66.     {
  67.         hStyles = nil;
  68.         goto cleanup;
  69.     }
  70.  
  71.     //    lock the style table
  72.     saveStylesLock = _WESetHandleLock(hStyles, true);
  73.  
  74.     //    fill in font table header
  75.     SetHandleSize(hFontTable, sizeof(WEFontTableHeader));
  76.     if ((err = MemError()) != noErr)
  77.         goto cleanup;
  78.     pFontTable = * (WEFontTableHandle) hFontTable;
  79.     _WEBlockClr(pFontTable, sizeof(WEFontTableHeader));
  80.     pFontTable->ftHeader.ftSignature = weFontTableSignature;
  81.     pFontTable->ftHeader.ftVersion = weCurrentFontTableVersion;
  82.  
  83.     //    init counters
  84.     fontCount = 0;
  85.     fontNameOffset = sizeof(WEFontTableHeader);
  86.  
  87.     //    walk the style table
  88.     nStyles = (*hWE)->nStyles;
  89.     for (    styleIndex = 0,
  90.             pStyle = (StyleTablePtr) *hStyles;
  91.             styleIndex < nStyles;
  92.             styleIndex++, pStyle++ )
  93.     {
  94.         //    skip this style table entry if it's either unused
  95.         //    or it references a font we have already processed
  96.         if (pStyle->refCount == 0)
  97.             continue;
  98.  
  99.         //    get the name of this font
  100.         BLOCK_CLR(fontName);
  101.         GetFontName(pStyle->info.runStyle.tsFont, fontName);
  102.  
  103.         //    caller can customize the building process by supplying
  104.         //    a mapping function
  105.         if (fontIDToNameProc != nil)
  106.         {
  107.             if ((err = CallWEFontIDToNameProc(pStyle->info.runStyle.tsFont, fontName, fontIDToNameProc)) != noErr)
  108.                 goto cleanup;
  109.         }
  110.  
  111.         //    calculate the space needed by the font name
  112.         //    for optimal alignment, make sure it's a multiple of 4
  113.         fontNameSize = StrLength(fontName) + 4;
  114.         fontNameSize &= ~3;
  115.  
  116.         //    append font name at the end of the font table
  117.         if ((err = _WESplice(hFontTable, fontName, fontNameSize, -1)) != noErr)
  118.             goto cleanup;
  119.  
  120.         //    create a new font table entry for this font
  121.         BLOCK_CLR(entry);
  122.         entry.ftNewFontID = entry.ftOldFontID = pStyle->info.runStyle.tsFont;
  123.         entry.ftEncoding = FontToScript(entry.ftOldFontID);
  124.         entry.ftNameOffset = fontNameOffset;
  125.         fontNameOffset += fontNameSize;
  126.  
  127.         //    add a new entry to the font table
  128.         pFontTable = * (WEFontTableHandle) hFontTable;
  129.         if ((err = _WESplice(hFontTable, &entry, sizeof(entry),
  130.                 sizeof(WEFontTableHeader) + sizeof(WEFontTableEntry) * fontCount)) != noErr)
  131.         {
  132.             goto cleanup;
  133.         }
  134.         fontCount++;
  135.  
  136.         //    mark all remaining entries in the style table which reference
  137.         //    the font ID we have just processed, so that we'll skip them
  138.         for (     styleIndex2 = styleIndex + 1, pStyle2 = pStyle + 1;
  139.                 styleIndex2 < nStyles;
  140.                 styleIndex2++, pStyle2++ )
  141.         {
  142.             if (pStyle2->info.runStyle.tsFont == entry.ftOldFontID)
  143.             {
  144.                 pStyle2->refCount = 0;
  145.             }
  146.         }
  147.     }    // for
  148.  
  149.     //    save font count in font table header
  150.     pFontTable = * (WEFontTableHandle) hFontTable;
  151.     pFontTable->ftHeader.ftNumEntries = fontCount;
  152.  
  153.     //    adjust name offsets in the font table
  154.     offsetAdjustment = sizeof(WEFontTableEntry) * fontCount;
  155.     for (    pEntry = &pFontTable->ftEntries[0];
  156.             fontCount > 0;
  157.             fontCount--, pEntry++ )
  158.     {
  159.         pEntry->ftNameOffset += offsetAdjustment;
  160.     }
  161.  
  162.     //    clear result code
  163.     err = noErr;
  164.  
  165. cleanup:
  166.     _WEForgetHandle(&hStyles);
  167.  
  168.     //    return result code
  169.     return err;
  170. }
  171.  
  172. pascal OSErr WEUpdateFontTable(Handle hFontTable, WEFontNameToIDUPP fontNameToIDProc, Boolean *wasChanged)
  173. {
  174.     WEFontTablePtr pFontTable;
  175.     WEFontTableEntryPtr pEntry;
  176.     ConstStr255Param fontName;
  177.     Size fontTableSize;
  178.     SInt32 fontCount;
  179.     Str255 systemFontName;
  180.     Boolean saveFontTableLock, changed;
  181.     OSErr err;
  182.  
  183.     //    assume font table won't change
  184.     changed = false;
  185.  
  186.     //    return an error code is hFontTable is nil
  187.     err = nilHandleErr;
  188.     if (hFontTable == nil)
  189.         goto cleanup;
  190.  
  191.     //    lock the font table
  192.     saveFontTableLock = _WESetHandleLock(hFontTable, true);
  193.     pFontTable = * (WEFontTableHandle) hFontTable;
  194.  
  195.     //    make sure the font table is a reasonable size
  196.     fontTableSize = GetHandleSize(hFontTable);
  197.     err = weCorruptDataErr;
  198.     if (fontTableSize < sizeof(WEFontTableHeader))
  199.         goto cleanup;
  200.  
  201.     //    check font table signature and entry count
  202.     if (pFontTable->ftHeader.ftSignature != weFontTableSignature)
  203.         goto cleanup;
  204.     if (fontTableSize < sizeof(WEFontTableHeader) + sizeof(WEFontTableEntry) * pFontTable->ftHeader.ftNumEntries)
  205.         goto cleanup;
  206.  
  207.     //    check font table version
  208.     //    assume we know how to handle all 1.x versions
  209.     //    if a new, incompatible format is designed in the future, it will
  210.     //    have to bump the version number to 2.x so this code can safely skip it
  211.     err = weNewerVersionErr;
  212.     if ((pFontTable->ftHeader.ftVersion & 0xFF000000) != 0x01000000)
  213.         goto cleanup;
  214.  
  215.     //    get name of system font
  216.     GetFontName(systemFont, systemFontName);
  217.  
  218.     //    walk the font table
  219.     for (    fontCount = pFontTable->ftHeader.ftNumEntries,
  220.             pEntry = &pFontTable->ftEntries[0];
  221.             fontCount > 0 ;
  222.             fontCount--, pEntry++ )
  223.     {
  224.         //    calculate pointer to font name
  225.         fontName = (ConstStr255Param) (((UInt32) pFontTable) + pEntry->ftNameOffset);
  226.  
  227.         //    by default, map font name to font ID using GetFNum()
  228.         GetFNum(fontName, &pEntry->ftNewFontID);
  229.  
  230.         //    GetFNum() returns zero either because the specified font
  231.         //    is the system font, or because it doesn't exist
  232.         if ((pEntry->ftNewFontID == 0) && !EqualString(fontName, systemFontName, false, false))
  233.         {
  234.             //    missing font:
  235.             //    use a replacement font with the same character encoding, if possible
  236.             pEntry->ftNewFontID = GetScriptVariable(GetScriptVariable(pEntry->ftEncoding,
  237.                         smEnabled) ? pEntry->ftEncoding : smSystemScript, smScriptAppFond);
  238.         }
  239.  
  240.         //    caller can customize the name resolution process
  241.         //    by specifying a mapping function
  242.         if (fontNameToIDProc != nil)
  243.         {
  244.             //    map font name to font ID using the supplied mapping function
  245.             if ((err = CallWEFontNameToIDProc(fontName, pEntry->ftOldFontID, &pEntry->ftNewFontID, fontNameToIDProc)) != noErr)
  246.                 goto cleanup;
  247.         }
  248.  
  249.         if (pEntry->ftOldFontID != pEntry->ftNewFontID)
  250.         {
  251.             changed = true;
  252.         }
  253.     }    //    for
  254.  
  255.     //    clear result code
  256.     err = noErr;
  257.  
  258. cleanup:
  259.     //    unlock the font table
  260.     if (hFontTable != nil)
  261.     {
  262.         _WESetHandleLock(hFontTable, saveFontTableLock);
  263.     }
  264.  
  265.     //    return wasChanged flag
  266.     if (wasChanged != nil)
  267.     {
  268.         *wasChanged = changed;
  269.     }
  270.  
  271.     //    return result code
  272.     return err;
  273. }
  274.  
  275. pascal OSErr WEUpdateStyleScrap(StScrpHandle hStyles, Handle hFontTable)
  276. {
  277.     WEFontTablePtr pFontTable;
  278.     WEFontTableEntryPtr pEntry;
  279.     ScrpSTElement *pStyle;
  280.     SInt32 fontCount, styleCount;
  281.     SInt16 oldFontID, newFontID;
  282.  
  283.     //    this function doesn't move memory, so we can
  284.     //    safely dereference hFontTable without locking it
  285.     pFontTable = * (WEFontTableHandle) hFontTable;
  286.  
  287.     //    remap font IDs in the style table associated with the specified WE instance
  288.     for (    fontCount = pFontTable->ftHeader.ftNumEntries,
  289.             pEntry = &pFontTable->ftEntries[0];
  290.             fontCount > 0 ;
  291.             fontCount--, pEntry++ )
  292.     {
  293.         oldFontID = pEntry->ftOldFontID;
  294.         newFontID = pEntry->ftNewFontID;
  295.  
  296.         //    skip inner loop if there's nothing to change
  297.         if (oldFontID == newFontID)
  298.         {
  299.             continue;
  300.         }
  301.  
  302.         for (    styleCount = (*hStyles)->scrpNStyles,
  303.                 pStyle = & (*hStyles)->scrpStyleTab[0];
  304.                 styleCount > 0;
  305.                 styleCount--, pStyle++ )
  306.         {
  307.             if (pStyle->scrpFont == oldFontID)
  308.             {
  309.                 pStyle->scrpFont = newFontID;
  310.             }
  311.         }    //    for
  312.     }    //    for
  313.  
  314.     return noErr;
  315. }
  316.